<template>
  <div class="wrap-box" v-loading="loading">
    <template v-if="showIm">
      <customer-list
        ref="customerList"
        :customer-list="customerList"
        :customer-service-number="customerServiceNumber"
        :conversation-info="ConversationInfo"
        :has-next-page="hasNextPage"
        @clickCustomer="clickCustomer"
        @loadMoreData="loadMoreData"
        @deleteIm="deleteIm"
        @updateList="updateList"
        @updateParamsSearch="updateParamsSearch"
      />
      <message-box
        v-loading="messageBoxLoading"
        ref="messageBox"
        :msg-list="msgList"
        :customer-service-number="customerServiceNumber"
        :conversation-number="conversationNumber"
        :hx-id-obj="hxIdObj"
        :customer-list="customerList"
        :user-detail="userDetail"
        @refresh="getOpenConversation(true)"
        :is-load-more="isLoadMore"
        :is-show-more="isShowMore"
        :source="source"
        @loadMore="loadMore"
        :time-out="timeOut ? timeOut : 0"
        :conversation-status="conversationStatus"
        :required-notes="RequiredNotes"
        :im-setting-config="ImSettingConfig"
        @Tab="Tab"
        :conversation-id="conversationId"
        :current-conversation-info="CurrentConversationInfo"
      />
      <chat-detail
        ref="chatdetail"
        :user-detail="userDetail"
        :source="source"
        :hx-id-obj="hxIdObj"
        :conversation-id="conversationId"
        :is-show-defalut="isShowDefalut"
        :im-setting-config="ImSettingConfig"
        @refresh="getOpenConversation(true)"
        @SetRequiredNotes="SetRequiredNotes"
        @saveBizRel="refreshCustomerInfo"
        :conversation-status="conversationStatus"
        :current-conversation-info="CurrentConversationInfo"
      />
    </template>
  </div>
</template>

<script>
import md5 from 'js-md5';
import EventBus from '@src/util/eventBus';
import * as IMApi from '@src/api/ImApi.js';
import MessageBox from './components/messageBox/message.vue';
import ChatDetail from './components/chatDetail/chatDetail.vue';
import CustomerList from './components/costomList/customerList.vue';
import { formatDate } from 'pub-bbx-utils';
import { parse } from '@src/util/querystring';
import { mapActions } from 'vuex';
import { getRootWindowInitData } from '@src/util/window';
import { PageRoutesTypeEnum } from 'pub-bbx-global/pageType/dist/enum/PageRoutesEnum'
import { openAccurateTab } from '@src/util/platform'

export default {
  components: {
    MessageBox,
    ChatDetail,
    CustomerList,
  },
  data() {
    return {
      conversationId: 0,
      msgList: [],
      customerList: [],
      hasNextPage: true,
      paramsSearch: {
        conversationStatus: 2,
      },
      userDetail: {},
      hxIdObj: {},
      loading: true,
      isShowDefalut: false,
      isLoadMore: false,
      isShowMore: false,
      source: '',
      conversationNumber: '',
      customerServiceNumber: '',
      timeOut: 0,
      conversationStatus: 2,
      pageNum: 1, // 会话列表分页页码
      pageSize: 100, // 会话列表每页查询量
      RequiredNotes: false,
      ConversationInfo: {},
      ImSettingConfig: {},
      updateListParam: {},
      CurrentConversationInfo: {},
      showIm: false,
      messageBoxLoading:false
    };
  },
  computed: {
    hasSystemSettingAuth() {
      return getRootWindowInitData()?.barPageList?.some(v=>v.menuKey === 'M_SYSTEM') ?? false
    }
  },
  destroyed() {
    EventBus.$off('addFileMessage', this.addFileMessage);
    EventBus.$off('refreshConversation', this.refreshConversation);
    EventBus.$off('refreshCustomerInfo', this.refreshCustomerInfo);
    EventBus.$off('getCustomerInfo', this.getCustomerInfo);
    EventBus.$off('updateUserDetail', this.updateUserDetail);
    EventBus.$off('updatedMsgList', this.updatedMsgList);
  },
  created() {
    EventBus.$on('addFileMessage', this.addFileMessage);
    EventBus.$on('refreshConversation', this.refreshConversation);
    EventBus.$on('refreshCustomerInfo', this.refreshCustomerInfo);
    EventBus.$on('getCustomerInfo', this.getCustomerInfo);
    EventBus.$on('updateUserDetail', this.updateUserDetail);
    EventBus.$on('updatedMsgList', this.updatedMsgList);
    // 监听websocket
    this.WatchWId();
    try {
      const query = parse(window.location.search) || {};
      this.conversationId = (query && query.id) || '';
    } catch (error) {}
    // 初始化页面判断是否要跳转到对应的会话
    if (sessionStorage.getItem('im_conversationId')) {
      this.conversationId = sessionStorage.getItem('im_conversationId');
      sessionStorage.removeItem('im_conversationId');
    }
  },
  async mounted() {
    try {
      await this.isCustomerService();
      // 获取当前未关闭的会话
      this.getOpenConversation(true);
      // 新建工单，新建事件权限以及模板列表
      this.get_operationalData();
      // 新建pass模板列表
      this.get_operationalDataByPass();
      this.lineConversation();
      this.getTenantImSetting();
      this.showIm = true;
      
    } catch (err) {
      console.log(err);
    } finally {
      this.loading = false;
    }
  },
  filters: {
    formatDate(value) {
      return formatDate(value, 'YYYY-MM-DD HH:mm:ss');
    },
  },
  watch: {
    customerList(val) {
      if (val && val.length <= 0) {
        this.msgList = [];
        this.isShowDefalut = true;
      } else {
        this.isShowDefalut = false;
      }
    },
  },
  methods: {
    ...mapActions(['get_operationalData', 'get_operationalDataByPass']),
    async getTenantImSetting() {
      try {
        const { code, data = {} } = await IMApi.getTenantImSetting();
        if (code !== 0) return;
        this.ImSettingConfig = data.config;
      } catch (error) {
        console.error('error', error);
      }
    },
    Tab(value) {
      this.$refs.chatdetail.activeName = value;
      this.$refs.chatdetail.$refs.ServiceNotes.Amendment = true;
    },
    // 监听全局变量，当点击气泡时切换聊天
    WatchWId() {
      // 开启监听postMessage
      window.addEventListener('message', ({ data }) => {
        const MessageData = data.data || null;
        if (MessageData) {
          /**
           * - websocket通知类型 -
           * newMessage新消息、
           * newConversation新会话、
           * forwardConversation转交会话、
           * assignConversation指派会话刷新列表、
           * lineConversation排队会话,
           * readMessage已读消息,
           * manualStartVideoRoom客服开始视频通话提醒
           * toTargetConversation 前端定义的类型 跳转到目标对话
           * customerServiceUnbind 解绑在线客服
           * customerServiceBind  绑定在线客服
           * touristLoginPhone 游客登录成功
           */
          let type = MessageData.notifyType;
          if (
            ![
              'newMessage',
              'newConversation',
              'forwardConversation',
              'assignConversation',
              'lineConversation',
              'readMessage',
              'manualStartVideoRoom',
              'toTargetConversation',
              'customerServiceUnbind',
              'customerServiceBind',
              'touristLoginPhone'
            ].includes(type)
          ) {
            return;
          }
          try {
            if (['newMessage'].includes(type)) {
              this.receiveNewMessage(MessageData);
            } else if (
              [
                'newConversation',
                'forwardConversation',
                'assignConversation',
                'lineConversation',
              ].includes(type)
            ) {
              // 刷新列表
              this.getOpenConversation(true);
              // 更新会话接待量
              this.lineConversation();
            } else if (['manualStartVideoRoom'].includes(type)) {
              // 更新会话列表数据
              this.updatedCustomerListMessageAndTime(MessageData.content)
              // 刷新当前聊下记录
              if (MessageData.content.conversationId == this.conversationId) {
                this.queryChatRecord({
                  conversationId: this.conversationId,
                  pageNum: 1,
                  pageSize: 10,
                  type: 1,
                });
              }
            } else if (['toTargetConversation'].includes(type)) {
              // 打开相对应的会话
              if (this.conversationId != MessageData.conversationId) {
                this.conversationId = MessageData.conversationId;
                this.getOpenConversation(true);
              } else {
                this.messageBoxscollBottom();
              }
            } else if (['readMessage'].includes(type)) {
              this.$nextTick(() => {
                this.readConversationToKF();
              });
            } else if (
              ['customerServiceUnbind', 'customerServiceBind'].includes(type)
            ) {
              window.location.reload();
            } else if (['touristLoginPhone'].includes(type)) {
              this.getOpenConversation(true);
            }
          } catch (error) {
            console.error(error);
          }
        }
      });
    },
    // 会话绑定事件，刷新当前会话状态
    refreshCustomerInfo() {
      const { conversationId } = this.hxIdObj;
      this.getCustomerInfo(conversationId);
      this.getOpenConversation();
    },
    receiveNewMessage(MessageData) {
      const { conversationId } = this.hxIdObj;
      if (MessageData.content.conversationId == conversationId) {
        // 当前开启的是当前会话
        this.pushMsg(MessageData.content);
        this.readConversationToKh(false);
        this.messageBoxscollBottom();
      } else {
        // 当前开启的是不是当前会话，刷新列表
        this.getOpenConversation();
      }
    },
    SetRequiredNotes(data) {
      this.RequiredNotes = data;
    },
    refreshConversation() {
      this.getOpenConversation(true);
    },
    getSign(ts, uid) {
      let str = `ts=${ts}&userId=${uid}SHOU_HOU_BAO`;
      return md5(str);
    },
    addFileMessage(msg) {
      this.isLoadMore = false;
      this.msgList && this.pushMsg(msg);
      this.messageBoxscollBottom();
      // this.getOpenConversation();
    },
    async clickCustomer(item, index) {
      try {
        this.messageBoxLoading = true
        this.$refs.customerList.isactive = index;
        this.timeOut = item.timeOut;
        this.source = item.source;
        this.conversationId = item.id;
        this.$set(this.hxIdObj, 'conversationId', item.id)
        this.customerServiceNumber = item.customerServiceNumber;
        this.conversationNumber = item.conversationNumber;
        this.conversationStatus = item.conversationStatus;
        this.CurrentConversationInfo = item;
        let parmas = {
          conversationId: item.id,
          pageNum: 1,
          pageSize: 10,
          type: 1,
        };
        // websocket气泡消息用到CurrentCustomerInfor
        sessionStorage.setItem('CurrentCustomerInfor', JSON.stringify(item));
        // 获取当前会话的聊天记录
        let p1 = this.queryChatRecord;
        // 获取当前会话下的客户信息
        let p2 = this.getCustomerInfo;
        // 把当前会话客户消息已读
        let p3 = this.readConversationToKh;
        await Promise.all([p1(parmas), p2(item.id), p3()])
        this.$refs.messageBox.showMore = true;
        this.messageBoxscollBottom();
        // 初始化AI
        this.fetchAIInit()
        
      } catch (err) {
        console.log(err)
      } finally {
        this.messageBoxLoading = false
      }
    },
    deleteIm({ id }) {
      this.$confirm(this.$t('im.imChat.tips1'), this.$t('common.base.toast'), {
        confirmButtonText: this.$t('common.base.confirm'),
        cancelButtonText: this.$t('common.base.cancel'),
        type: 'warning',
        customClass: 'ShowcustomClass',
      })
        .then(async () => {
          IMApi.closeConversation({ id })
            .then(res => {
              if (res.code == 0) {
                this.msgList = [];
                this.userDetail = {};
                this.$platform.notification({
                  title: this.$t('common.base.success'),
                  type: 'success',
                });
                this.getOpenConversation(false);
              }
            })
            .catch(err => {
              console.error(err);
            });
        })
        .catch(() => {});
    },
    // 更新会话列表数据
    updateList() {
      this.getOpenConversation(true);
    },
    // 获取当前会话下的客户信息
    async getCustomerInfo(conversationId){
      this.userDetail = {}
      try{
        const res = await IMApi.getCustomerInfo({ conversationId })
        if (res.code == 0) {
            this.userDetail = res && res.data;
        }
      }catch(err){
        console.log(err)
      }
    },
    // 获取聊天记录
    async queryChatRecord(params, isLoadMore){
      try{
        const res = await IMApi.queryChatRecord(params)
        if (res.code == 0) {
            this.msgList = res.data.list;
            this.total = res.data.total;
            if (isLoadMore) {
              this.isShowMore = false;
              this.isLoadMore = false;
              this.$nextTick(() => {
                const id = this.msgList[this.msgList.length - 10].id;
                let ele = document.querySelector(`.item-${id}`);
                let pele = document.querySelector('.messagebox-container');
                pele.scrollTop = ele.offsetTop - ele.offsetHeight / 2;
              });
            } else {
              this.isShowMore = res.data.total > 10;
            }
          }
      }catch(err){
        console.log(err)
      }
    },

    loadMore(obj) {
      this.isLoadMore = true;
      let { conversationId, isLoadMore } = obj;
      let parmas = {
        conversationId,
        pageNum: 1,
        pageSize: this.total,
        type: 1,
      };
      this.queryChatRecord(parmas, isLoadMore);
    },
    loadMoreData() {
      this.getOpenConversation(false, 'hasLoadMore');
    },
    // 查询会话列表 flag:更新数据是会回到当前选中的会话
    getOpenConversation(flag, hasLoadMore) {
      return new Promise((resolve, reject) => {
        // 分页参数
        let paramsData = {
          pageNum: hasLoadMore ? ++this.pageNum : 1,
          pageSize: this.pageSize,
        };
        let params = Object.assign(paramsData, this.paramsSearch);
        params.conversationStatus = params.conversationStatus == 0 ? '' : params.conversationStatus;
        IMApi.getOpenConversation(params)
          .then(res => {
            if (res.code == 0) {
              this.lineConversation();
              if (hasLoadMore && this.hasNextPage)
                this.customerList.push(...res.data.list);
              if (!hasLoadMore) {
                this.pageNum = 1;
                this.customerList = res.data.list;
              }
              this.hasNextPage = res.data.hasNextPage;
              if (flag) {
                // let index = this.conversationId ? this.customerList.findIndex(item=> {
                //   return this.conversationId == item.id
                // }) : 0
                if (this.conversationId) {
                  let index = this.customerList.findIndex(
                    item => this.conversationId == item.id
                  );
                  console.log(index);
                  // 列表更新，找到更新后的会话位置点击
                  if (index > -1) {
                    this.clickCustomer(this.customerList[index], index);
                  } else if (this.customerList.length) {
                    // 列表更新，先前会话已经消失。但会话列表有数据，选择第一个
                    this.clickCustomer(this.customerList[0], 0);
                  }
                }
                this.loading = false;
              }
              resolve();
            } else if (res.code == 1002) {
              this.isShowDefalut = true;
              this.loading = false;
              this.$platform.alert(res.message);
              reject();
            } else {
              this.$message.error(res.message);
            }
          })
          .catch(err => {
            console.error(err);
            this.loading = false;
            reject();
          });
      });
    },
    // 查询排队数据
    lineConversation() {
      IMApi.getConversationDealNum().then(res => {
        if (res.code === 0) {
          this.ConversationInfo = res.data;
        }
      });
    },
    // 更新查询参数
    updateParamsSearch(params) {
      this.paramsSearch = params;
    },
    // 把当前会话客服消息已读
    readConversationToKF() {
      this.msgList.map(v => {
        v.status = 3;
      });
    },
    // 把当前会话客户消息已读 judgeUnreadCount:是否要对unreadCount进行判断
    async readConversationToKh(judgeUnreadCount = true){
      let index = this.customerList.findIndex(
        item => this.conversationId == item.id
      );
      // 当前会话有未读消息调用
      if (judgeUnreadCount && !this.customerList[index].unreadCount) return;

      let params = {
        status: 3,
        conversationId: this.conversationId,
        sendType: 2, // 客户
      };
      try{
        const res = await IMApi.editMessageByConversation(params)
        if (res?.code == 0) {
            this.customerList[index].unreadCount = 0;
        }
      }catch(err){
        console.log(err)
      }
    },
    // 判断当前登录账号是否为客服坐席
    async isCustomerService() {
      try {
        const { code, data } = await IMApi.isCustomerService();
        if (code == 0 && data.isCustomerService) {
          this.showIm = true;
          return Promise.resolve(true);
        }
        const h = this.$createElement
        const childrenEl = h('span', this.$t('im.imChat.tips2'))
        const childrenEl2 = this.hasSystemSettingAuth ? h('span', {
          domProps: {
            innerHTML: this.$t('im.imChat.goSet')
          },
          style: {
            color: this.getThemeColor,
            cursor: 'pointer'
          },
          on: {
            click: this.toImSetting
          },
        }) : ''
        const wrapEl = h('div', {}, [childrenEl, childrenEl2])
        this.$alert(wrapEl, this.$t('common.base.toast'), {
          confirmButtonText: this.$t('common.base.confirm'),
          showClose:false,
          callback:()=>{
            this.closeTab()
          }
        });
        return Promise.reject(this.$t('im.imChat.tips2'));
      } catch (err) {
        this.$message.error(this.$t('common.base.tip.systemIsError'));
        return Promise.reject(this.$t('im.imChat.tips2'));
      }
    },
    messageBoxscollBottom() {
      this.$refs.messageBox.scollBottom();
    },
    closeTab() {
      let id = window.frameElement.dataset.id;
      this.$platform.closeTab(id);
    },
    updateUserDetail(data){
      this.userDetail = data
    },
    // 更新聊天数据
    updatedMsgList(params = {}) {
      let type = params?.type;
      if (!type) return;
      switch (type) {
        case 'editMoreEdit':
          // 添加moreEdit字段
          this.msgList.map((v, i) => {
            // 销毁掉其它moreEdit组件
            this.$set(this.msgList[i], 'moreEdit', false);
          });
          this.$set(this.msgList[params.idx], 'moreEdit', params.val);
          break;
        case 'withdraw':
          //撤回消息
          this.msgList.splice(params.idx, 1, params.msgInfo);
          this.updatedCustomerListMessageAndTime(params.msgInfo)
          break;
        case 'addConversationMessage':
          this.msgList.unshift(...params.val)
          this.resetScrollBarHeight(document.querySelector('.messagebox-container'))
          break;
        // 追加新消息
        case 'pushMsg':
          this.pushMsg(params.msg)
          break;
        default:
          console.log(`未知类型`);
      }
    },
    resetScrollBarHeight(node) {
      //重置滚动条高度
      const previousScrollHeightMinusTop = node.scrollHeight - node.scrollTop;
      this.$nextTick(() => {
        node.scrollTop = node.scrollHeight - previousScrollHeightMinusTop;
      });
    },
    // 追加新消息
    pushMsg(msg){
      this.msgList.push(msg)
      this.updatedCustomerListMessageAndTime(msg)
      
      console.log('pushMsg', msg)
      EventBus.$emit('pushNewMessage');
    },
    //更新会话列表最新消息和时间
    updatedCustomerListMessageAndTime(data){
      let {conversationId,recentTime,recentMessage} = data
      if(!conversationId) return

      let idx = this.customerList.findIndex(v => v.id == conversationId )
      if(idx == -1) return
      let itemData = {...this.customerList[idx],recentTime,recentMessage }
      this.$set(this.customerList,idx,itemData)
    },
    toImSetting(){
      this.closeTab()
      openAccurateTab({
        type: PageRoutesTypeEnum.PageSettingImSetting,
      })
    },
    fetchAIInit() {
      this.$refs.messageBox?.fetchAIInit()
    }
  },
};
</script>
<style lang="scss">
.ShowcustomClass {
  margin-top: -60px;
}
</style>
<style lang="scss" scoped>
body,
html {
  height: 100%;
}
.wrap-box {
  display: flex;
  padding: 12px;
  height: 100vh;
}

.wrap-box {
  min-width: 1022px;
}
</style>
